package com.tzy.evaluation.service;

import com.tzy.common.entity.UserLikes;
import com.tzy.common.utils.RedisKeyUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * Redis服务;还需要有redis配置类 RedisConfig
 */
@Service
@Slf4j
public class RedisService extends MessageListenerAdapter {
    @Resource(name = "objectRedisTemplate")
    private RedisTemplate<String, Object> objectRedisTemplate;
    @Resource
    private RedisTemplate redisTemplate;

    //    @Override
    public List<UserLikes> getLikedDataFromRedis() {
        Cursor<Map.Entry<Object, Object>> cursor = redisTemplate.opsForHash().scan(RedisKeyUtils.MAP_KEY_USER_LIKED, ScanOptions.NONE);
        List<UserLikes> list = new ArrayList<>();
        while (cursor.hasNext()) {
            Map.Entry<Object, Object> entry = cursor.next();
            String key = (String) entry.getKey();
            //分离出 likedUserId，likedPostIdString[] split = key.split("::");
            String[] split = new String[0];
            String likedUserId = split[0];
            String likedPostId = split[1];
            Integer value = (Integer) entry.getValue();
            //组装成 UserLike 对象UserLike userLike = new UserLike(likedUserId, likingUserId, value);
            UserLikes userLike = new UserLikes();
            list.add(userLike);
            //存到 list 后从 Redis 中删除
            redisTemplate.opsForHash().delete(RedisKeyUtils.MAP_KEY_USER_LIKED, key);
        }
        return list;
    }

    /**
     * 点赞 SETBIT - BITMAP
     *
     * @param key    键
     * @param offset 偏移量; 评价编号
     * @param bit    值 true or false
     * @return
     */
    public Boolean setBit(String key, long offset, boolean bit) {
        Boolean aBoolean = objectRedisTemplate.opsForValue().setBit(key, offset, bit);
        return aBoolean;
    }

    /**
     * 设置值
     *
     * @param key
     * @param value
     * @param second 过期时间:单位秒
     */
    public void setString(String key, String value, int second) {
        objectRedisTemplate.opsForValue().set(key, value, second, TimeUnit.SECONDS);
    }

    /**
     * 获取值
     *
     * @param key
     * @return
     */
    public String getString(String key) {
        Object o = objectRedisTemplate.opsForValue().get(key);
        if (o == null)
            return null;
        return (String) o;
    }

    /**
     * 获取值
     *
     * @param key
     * @return
     */
    public Integer getInteger(String key) {
        Object o = objectRedisTemplate.opsForValue().get(key);
        if (o == null)
            return null;
        return (Integer) o;
    }

    public void setObject(String key, Object obj) {
        objectRedisTemplate.opsForValue().set(key, obj);
    }

    public <T> T getObject(String key) {
        Object o = objectRedisTemplate.opsForValue().get(key);
        return (T) o;
    }

    public <T extends Object> T getObject(String key, Class clazz) {
        Object o = objectRedisTemplate.opsForValue().get(key);
        if (o == null) return null;
        if (clazz.isInstance(o))
            if (o.getClass().getName().equalsIgnoreCase(clazz.getName())) {
                return (T) o;
            }
        log.error("{}的值不是{}的实例", key, clazz.getName());
        return null;
    }

    /**
     * 自增 1
     *
     * @param key
     * @return
     */
    public Long increment(String key) {
//        redisTemplate.opsForHash()
        Long increment = objectRedisTemplate.opsForValue().increment(key);
        return increment;
    }

    /**
     * redis订阅消息处理
     */
    @Override
    public void onMessage(Message message, byte[] pattern) {
//        super.onMessage(message, pattern);
        log.info("channel:{} message:{}", new String(message.getChannel()), new String(message.getBody()));
    }
    //    @Resource
//    private ReactiveRedisTemplate reactiveRedisTemplate;

//    public void run(String... args) throws Exception {
//        reactiveRedisTemplate
//                .opsForValue()
//                .set("name", "李四")
//                .subscribe(b -> log.info("set result:{}", b),
//                        e -> log.error("set data error:{}", e));
//    }

}
